package com.richie696.utils;

import org.apache.commons.lang3.ArrayUtils;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

/**
 * <pre>
 * 【v1.3更新记录(2012-11-02) -- By 王锦阳】
 *  1. 改进需要加密的字符串的读取编码规则，由之前版本中的固定值改为现在可自定义修改编码方式的；
 *  2. 新增还原默认编码格式的方法；
 * 【v1.2更新记录(2012-10-12) -- By 王锦阳】
 *  1. 可指定编码字符集，替代之前版本中使用的字符串方式，最大限度减少因外部给错参数而导致的加密失败；
 * 【v1.1更新记录(2012-09-28) -- By 王锦阳】
 *  1. 更新加密方式，支持 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512 算法；
 *  2. 去除测试用的 main() 方法；
 * 【v1.0更新记录(2011-04-16) -- By 王锦阳】
 *  1. 原始版本创建，主要用于 MD5 加密功能；
 * </pre>
 * 程序安全加密工具类：用于对字符串进行MD5和SHA-1加密的引擎类
 *
 * @author richie696
 * @version 1.3
 * @since 2012-11-02
 */
public class SecurityUtils {

    /**
     * 加密字符串字符集格式的常量字符串
     */
    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

    /**
     * 构造方法：私有构造方法（禁止实例化）
     */
    private SecurityUtils() {
    }

    /**
     * 加密方法：实现字符串加密的方法
     *
     * @param encryptType     加密类型（请使用本类提供的常量字符串）
     * @param contentString 传入的待加密字符串
     * @return 返回加密字符串
     */
    public static String encryption(EncryptType encryptType, String contentString, Charset... charset) {
        // 捕捉加密过程中产生的异常
        try {
            // 创建加密引擎类对象
            MessageDigest md = MessageDigest.getInstance(encryptType.getValue());
            // 传入需要加密的字符串
            md.update(contentString.getBytes(ArrayUtils.isNotEmpty(charset) ? charset[0].name() : DEFAULT_CHARSET.name()));
            // 执行加密并保存到字节数组中
            byte[] digest = md.digest();
            int result;
            // 声明StringBuffer对象
            StringBuilder buffer = new StringBuilder();
            // 将引擎类处理过的加密数据进行转换
            for (byte byteCode : digest) {
                result = byteCode;
                if (result < 0) {
                    result += 256;
                }
                if (result < 16) {
                    buffer.append("0");
                }
                // 得出计算结果并存入StringBuffer对象
                buffer.append(Integer.toHexString(result));
            }
            // 返回加密后的结果
            return buffer.toString();
        } catch (Exception e) {
            // 如果出错则打印提示并记录
            e.printStackTrace();
        }
        // 如果出错则返回空
        return null;
    }

    /**
     * 加密类型枚举内部类
     *
     * @author richie696
     * @version 1.0
     */
    public enum EncryptType {

        /**
         * MD2
         */
        MD2("MD2"),
        /**
         * MD5
         */
        MD5("MD5"),
        /**
         * SHA-1
         */
        SHA_1("SHA-1"),
        /**
         * SHA-256
         */
        SHA_256("SHA-256"),
        /**
         * SHA-384
         */
        SHA_384("SHA-384"),
        /**
         * SHA-512
         */
        SHA_512("SHA-512"),

        HmacSHA1("HmacSHA1");

        private final String value;

        EncryptType(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

    }

}
